package com.example.sea.back.common.shiro;

import com.example.sea.back.common.context.SessionKeyContext;
import com.example.sea.core.data.user.AuthRoleEnum;
import com.example.sea.core.data.user.AuthUserEunm;
import com.example.sea.core.data.user.entity.AuthPermission;
import com.example.sea.core.data.user.entity.AuthRole;
import com.example.sea.core.data.user.entity.AuthUser;
import com.example.sea.core.data.user.model.AuthPermissionModel;
import com.example.sea.core.data.user.service.AuthPermissionService;
import com.example.sea.core.data.user.service.AuthRoleService;
import com.example.sea.core.data.user.service.AuthUserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

/**
 * 自定义ShiroRealm
 */
public class ShiroRealm extends AuthorizingRealm {

    private Logger log=LoggerFactory.getLogger(ShiroRealm.class);

    @Autowired
    private AuthUserService authUserService;

    @Autowired
    private AuthRoleService authRoleService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        /*
         * 当没有使用缓存的时候，不断刷新页面的话，这个代码会不断执行，
         * 当其实没有必要每次都重新设置权限信息，所以我们需要放到缓存中进行管理；
         * 当放到缓存中时，这样的话，doGetAuthorizationInfo就只会执行一次了，
         * 缓存过期之后会再次执行。
         */
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        AuthUser authUser = (AuthUser) principals.getPrimaryPrincipal();
        log.info("{}:权限控制开始",authUser.getAccount());
        //添加角色和权限
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        AuthRole authRole = authRoleService.findById(authUser.getRoleId());
        simpleAuthorizationInfo.addRole(authRole.getCode());
        log.info("{}:权限控制开始｛角色：{}｝",authUser.getAccount(),authRole.getName());
        List<AuthPermissionModel> authPermissionModels = authRoleService.findByIdToRolePermission(authRole.getId());
        for (AuthPermissionModel authPermissionModel:authPermissionModels) {
            if (authPermissionModel.getIsRole()==AuthRoleEnum.IS_ROLE_Y.getValue()){
                simpleAuthorizationInfo.addStringPermission(authPermissionModel.getCode());
                log.info("{}:权限控制开始｛角色：{},权限：{}｝",authUser.getAccount(),authRole.getName(),authPermissionModel.getName());
                for (AuthPermissionModel menu:authPermissionModel.getAuthPermissionModels()) {
                    simpleAuthorizationInfo.addStringPermission(menu.getCode());
                    log.info("{}:权限控制开始｛角色：{},权限：{}｝",authUser.getAccount(),authRole.getName(),menu.getName());
                }

            }
        }
        log.info("{}:权限控制结束",authUser.getAccount());
        return simpleAuthorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String account = String.valueOf(authenticationToken.getPrincipal());
        log.info("{}:登陆验证开始",account);
        AuthUser authUser = authUserService.findByLogin(account);
        if (null == authUser) {
            log.info("{}:验证失败，用户不存在",account);
            throw new UnknownAccountException();
        } else if (authUser.getState()==AuthUserEunm.STATE_NO.getValue()) {
            log.info("{}:验证失败，用户被冻结",account);
            throw new DisabledAccountException();
        } else{
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(authUser, authUser.getPassword(), getName());
            Subject subject = SecurityUtils.getSubject();
            subject.getSession().setAttribute(SessionKeyContext.SESSION_LOGIN_ADMIN_USER, authUser);
            log.info("{}:账号密码验证成功",account);
            return simpleAuthenticationInfo;
        }
    }
}
